package com.totoro.mybatis.sharding.config;

import com.mysql.jdbc.jdbc2.optional.MysqlDataSource;
import com.totoro.mybatis.sharding.plugin.ShardingPlugin;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.logging.log4j.util.PropertiesUtil;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.util.StringUtils;

import javax.sql.DataSource;
import java.io.IOException;
import java.util.*;

/**
 * Created by Niki on 2018/8/23 11:53
 */
@Configuration
@MapperScan(basePackages = {"com.totoro.mybatis.sharding.dao"}, sqlSessionFactoryRef = "sqlSessionFactory")
public class MybatisConfig {

    @Value("${spring.datasource.db.sharding.table2DB}")
    private String table2DBPath;
    @Value("${spring.datasource.db.sharding.table2Strategy}")
    private String table2StrategyPath;

    @Bean
    @ConfigurationProperties(prefix = "spring.datasource.db")
    public DataSource dataSource() {
        DataSource dataSource = DataSourceBuilder.create().type(MysqlDataSource.class).build();
        return dataSource;
    }

    @Bean
    public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
        SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
        sqlSessionFactoryBean.setDataSource(dataSource);

        //设置分库分表插件
        ShardingPlugin shardingPlugin = new ShardingPlugin();

        //设置表对应库
        setTable2DB(shardingPlugin);

        //设置表对应的分表分库策略
        setShardingStrategy(shardingPlugin);

        List<Interceptor> interceptors = new ArrayList<Interceptor>();
        interceptors.add(shardingPlugin);
        sqlSessionFactoryBean.setPlugins(interceptors.toArray(new Interceptor[interceptors.size()]));

        return sqlSessionFactoryBean.getObject();
    }

    @Bean
    public SqlSessionTemplate sqlSessionTemplate(SqlSessionFactory sqlSessionFactory) {
        return new SqlSessionTemplate(sqlSessionFactory);
    }

    /**
     * 分表分库插件设置表与库对应的容器
     * @param shardingPlugin 分表分库插件
     */
    private void setTable2DB(ShardingPlugin shardingPlugin) throws IOException {
        if (StringUtils.isEmpty(table2DBPath)) {
            //没有配置表与DB对应文件，则采用默认文件
            table2DBPath = "/sharding/table2DB.properties";
        }
        Resource resource = new ClassPathResource(table2DBPath);
        Properties table2DBProperties = new Properties();
        table2DBProperties.load(resource.getInputStream());
        Set<Object> keys = table2DBProperties.keySet();
        Map<String, String> table2DBMap = shardingPlugin.getTable2DB();
        for (Object key : keys) {
            table2DBMap.put(key.toString(), table2DBProperties.getProperty(key.toString()));
        }
    }

    /**
     * 设置表对应的分表分库策略容器
     * @param shardingPlugin 分表分库插件
     */
    private void setShardingStrategy(ShardingPlugin shardingPlugin) {
        if (StringUtils.isEmpty(table2StrategyPath)) {
            table2StrategyPath = "sharding/mybatis_sharding_config.xml";
        }
        Properties properties = new Properties();
        properties.setProperty("configsLocation", table2StrategyPath);
//        shardingPlugin.setProperties(properties);
    }
}
